package com.yanggu.scala.chapater18.contextbounds

//上下文界定
//与view bounds一样, context bounds(上下文界定)也是隐式参数的语法糖
//为语法上的方便，引入了"上下文界定"这个概念
object ContextBoundsDemo01 {

  implicit val personComparetor = new Ordering[Person] {
    override def compare(p1: Person, p2: Person): Int =
      p1.age - p2.age
  }

  def main(args: Array[String]): Unit = {
    val p1 = new Person("mary", 30)
    val p2 = new Person("smith", 35)
    val compareComm4 = new CompareComm4(p1,p2)
    println(compareComm4.geatter)
    val compareComm5 = new CompareComm5(p1,p2)
    println(compareComm5.geatter)
    val compareComm6 = new CompareComm6(p1,p2)
    println(compareComm6.geatter)
  }

}

//这里需要对[T: Ordering]进行说明。
//1. 和之前的泛型上下界、视图界定不同。这里的泛型T和Ordering之间没有T必须是Ordering的子类或者是父类
//2. 会自动添加一个隐式转换参数。(implicit comparetor: Ordering[T]), 存在着需要将T => Ordering[T]的隐式转换
//3. 并且调用CompareComm6方法时必须有一个可用的隐式值Ordering[T]存在

//方式1。
class CompareComm4[T: Ordering](obj1: T, obj2: T)(implicit comparetor: Ordering[T]) {

  def geatter = if (comparetor.compare(obj1, obj2) > 0) obj1 else obj2

}

//方式2,将隐式参数放到方法内
class CompareComm5[T: Ordering](o1: T, o2: T) {

  def geatter = {
    def f1(implicit cmptor: Ordering[T]) = cmptor.compare(o1, o2)

    if (f1 > 0) o1 else o2
  }

}

//方式3,使用implicitly语法糖，最简单(推荐使用)
class CompareComm6[T: Ordering](o1: T, o2: T) {

  def geatter = {
    //这句话就是会发生隐式转换，获取到隐式值 personComparetor
    //在隐式转换的作用域中必须存在Ordering[T]这样的隐式值
    //从上线文中获取对应的隐式参数
    val comparetor = implicitly[Ordering[T]]
    println("CompareComm6 comparetor" + comparetor.hashCode())
    if (comparetor.compare(o1, o2) > 0) o1 else o2
  }

}

//一个普通的Person类
class Person(val name: String, val age: Int) {
  override def toString = this.name + "\t" + this.age
}

